package com.cy.springcloud.controllers;

import com.cy.springcloud.hystrix.CustomHystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @Description: 测试hystrix熔断器功能
 * @ClassName: HystrixController
 * @Author: chenyu
 * @Date: 2025/1/6 16:32
 */
@RestController
public class HystrixController {
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/web/hystrix", method = RequestMethod.GET)
    @HystrixCommand(fallbackMethod = "error", commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    }, ignoreExceptions = Exception.class)
    //对当前方法开启熔断
    //发生熔断后，调用error方法
    //hystrix默认超时时间是1000毫秒，如果后端响应超过此时间，就会触发熔断器
    //如果远程服务有一个异常抛出后，我们不希望进入到服务降级方法中去处理，而是直接将异常抛给用户，添加ignoreExceptions = Exception.class
    public String hystrix() {
        //模拟响应时间超过hystrix等待时间，进而触发熔断
//        try {
//            Thread.sleep(4000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        //模拟异常
         int i = 10 / 0;
        //调用SpringCloud服务提供者提供的服务
        //return restTemplate.getForEntity("http://localhost:8080/hello", String.class).getBody();
        return restTemplate.getForEntity("http://01-springcloud-service-provider/hello", String.class).getBody();
    }

    /**
     * 熔断的回调方法，也就是降级方法
     * @return java.lang.String
     * @date 2025/1/6 17:11
     */
    public String error(Throwable throwable) {
        //访问远程服务失败，该如何处理？这些处理逻辑就可以写在这个方法里
        System.out.println("异常：" + throwable.getMessage());
        return "error";
    }

    /**
     * 自定义类继承HystrixCommand来实现hystrix请求
     * @return java.lang.String
     * @date 2025/1/6 17:40
    */
    @RequestMapping(value = "/web/hystrix2", method = RequestMethod.GET)
    public String hystrix2() throws ExecutionException, InterruptedException {
        CustomHystrixCommand customHystrixCommand = new CustomHystrixCommand(
                com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), restTemplate);

        //同步调用
        //return customHystrixCommand.execute();
        //异步调用
        Future<String> future = customHystrixCommand.queue();
        //写一些业务逻辑
        //阻塞
        return future.get();
    }
}
